package online

import (
	"errors"
	"server/common"

	"github.com/mitchellh/mapstructure"
	"github.com/sirupsen/logrus"
)

// -------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------
func (s *OnlineService) checkLogoutReqData(data common.LogoutReqData) error {
	// Check if user ID is provided
	if data.UserId == "" {
		return errors.New("user ID is required in logout request")
	}

	// Check if user exists
	if s.userMgr.GetUserByUserId(data.UserId) == nil {
		return errors.New("user does not exist")
	}

	return nil
}

// -------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------
func (s *OnlineService) sendSuccessLogoutResponse(rid string, userId string, from common.ServiceInfo,
	connId string) {
	resMsg := common.Message{
		Cmd: common.LOGOUT_RES,
		Rid: rid,
		Data: common.ResMsgData{
			Code: 0,
			Msg:  "logout successful",
			Data: common.LogoutResData{
				UserId: userId,
			},
		},
	}
	s.dispatcher.Dispatch(resMsg, s.serviceInfo, from, connId)
}

// -------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------
func (s *OnlineService) sendFailureLogoutResponse(rid string, msg string, from common.ServiceInfo,
	connId string) {
	resMsg := common.Message{
		Cmd: common.LOGOUT_RES,
		Data: common.ResMsgData{
			Code: 1,
			Msg:  msg,
		},
	}
	s.dispatcher.Dispatch(resMsg, s.serviceInfo, from, connId)
}

// -------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------
func (s *OnlineService) handleLogoutReq(msg common.Message, from common.ServiceInfo,
	connId string) error {
	common.Logger(common.SERVICE_TYPE_ONLINE, msg.Rid).WithFields(logrus.Fields{
		"msg":    common.ToJson(msg),
		"from":   from,
		"connId": connId,
	}).Info("call handleLogoutRequest")

	var logoutData common.LogoutReqData
	if err := mapstructure.Decode(msg.Data, &logoutData); err != nil {
		common.Logger(common.SERVICE_TYPE_ONLINE, msg.Rid).WithError(err).
			Error("failed to parse logout request")
		s.sendFailureLogoutResponse(msg.Rid, "invalid logout request data", from, connId)
		return nil
	}

	if err := s.checkLogoutReqData(logoutData); err != nil {
		common.Logger(common.SERVICE_TYPE_ONLINE, msg.Rid).WithError(err).
			Error("invalid logout request data")
		s.sendFailureLogoutResponse(msg.Rid, err.Error(), from, connId)
		return nil
	}

	onlineService.userMgr.RemoveUser(logoutData.UserId)

	s.sendSuccessLogoutResponse(msg.Rid, logoutData.UserId, from, connId)

	// Notify other users about the logout
	for _, user := range onlineService.userMgr.GetUserListWithoutSelf(logoutData.UserId) {
		notifyMsg := common.Message{
			Cmd: common.LOGOUT_NOTIFY,
			Rid: msg.Rid,
			Data: common.LogoutNotifyData{
				UserId: logoutData.UserId,
			},
		}
		s.dispatcher.Dispatch(notifyMsg, s.serviceInfo, user.ServiceInfo, user.ConnId)
	}

	return nil
}
